package com.wormhole.wormholemanagement.service.impl;

import com.wormhole.wormholemanagement.entity.OperationLog;
import com.wormhole.wormholemanagement.entity.Operator;
import com.wormhole.wormholemanagement.repository.OperationLogRepository;
import com.wormhole.wormholemanagement.repository.OperatorRepository;
import com.wormhole.wormholemanagement.service.OperatorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

@Service
public class OperatorServiceImpl implements OperatorService {

    private final OperatorRepository operatorRepository;
    private final OperationLogRepository logRepository;
    private final PasswordEncoder passwordEncoder;

    @Autowired
    public OperatorServiceImpl(OperatorRepository operatorRepository,
                               OperationLogRepository logRepository,
                               PasswordEncoder passwordEncoder) {
        this.operatorRepository = operatorRepository;
        this.logRepository = logRepository;
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    @Transactional
    public Operator createOperator(Operator operator) {
        operator.setPassword(passwordEncoder.encode(operator.getPassword()));
        operator.setCreatedAt(LocalDateTime.now().toString());
        operator.setUpdatedAt(LocalDateTime.now().toString());
        operator.setActive(true);
        Operator savedOperator = operatorRepository.save(operator);

        // Log the operation (assuming system admin is performing this operation)
        OperationLog log = new OperationLog();
        log.setOperatorId(1L); // Assuming admin ID is 1
        log.setOperationType("create");
        log.setTableName("operators");
        log.setRecordId(savedOperator.getOperatorId());
        log.setOperationDetails("Created operator with username: " + savedOperator.getUsername());
        log.setOperationTime(LocalDateTime.now());
        logRepository.save(log);

        return savedOperator;
    }

    @Override
    @Transactional
    public Operator updateOperator(Long id, Operator operator) {
        Operator existingOperator = operatorRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("Operator not found with id: " + id));

        // Update fields
        existingOperator.setUsername(operator.getUsername());
        if (operator.getPassword() != null && !operator.getPassword().isEmpty()) {
            existingOperator.setPassword(passwordEncoder.encode(operator.getPassword()));
        }
        existingOperator.setRealName(operator.getRealName());
        existingOperator.setDepartment(operator.getDepartment());
        existingOperator.setRole(operator.getRole());
        existingOperator.setActive(operator.getActive());
        existingOperator.setUpdatedAt(LocalDateTime.now().toString());
        existingOperator.setExtendedData(operator.getExtendedData());

        Operator updatedOperator = operatorRepository.save(existingOperator);

        // Log the operation
        OperationLog log = new OperationLog();
        log.setOperatorId(1L); // Assuming admin ID is 1
        log.setOperationType("update");
        log.setTableName("operators");
        log.setRecordId(updatedOperator.getOperatorId());
        log.setOperationDetails("Updated operator with username: " + updatedOperator.getUsername());
        log.setOperationTime(LocalDateTime.now());
        logRepository.save(log);

        return updatedOperator;
    }

    @Override
    @Transactional
    public void deleteOperator(Long id) {
        Operator operator = operatorRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("Operator not found with id: " + id));

        operatorRepository.delete(operator);

        // Log the operation
        OperationLog log = new OperationLog();
        log.setOperatorId(1L); // Assuming admin ID is 1
        log.setOperationType("delete");
        log.setTableName("operators");
        log.setRecordId(id);
        log.setOperationDetails("Deleted operator with username: " + operator.getUsername());
        log.setOperationTime(LocalDateTime.now());
        logRepository.save(log);
    }

    @Override
    public Operator getOperatorById(Long id) {
        return operatorRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("Operator not found with id: " + id));
    }

    @Override
    public Operator getOperatorByUsername(String username) {
        return operatorRepository.findByUsername(username)
                .orElseThrow(() -> new RuntimeException("Operator not found with username: " + username));
    }

    @Override
    public Page<Operator> getAllOperators(Pageable pageable) {
        return operatorRepository.findAll(pageable);
    }
}